<?php
/**
 * @Author: gan
 * @Description: 如果使用的话，直接类中 use CurlTrait;
 * @File:  CurlTrait
 * @Version: 1.0.0
 * @Date: 2021/12/27 1:35 下午
 */

declare(strict_types=1);

namespace RX\Traits;

use EasySwoole\HttpClient\Bean\Response;
use EasySwoole\HttpClient\Exception\InvalidUrl;
use EasySwoole\HttpClient\HttpClient;
use RX\Enums\NetworkEnum;
use RX\Exception\BizException;

trait CurlTrait
{
    /**
     * post
     * @param string $url 地址
     * @param array $data 数据
     * @param bool $isJson 是否json格式
     * @param int $timeout 超时时间，秒
     * @param array $headers header头
     * @return mixed
     * @throws BizException
     * @throws InvalidUrl
     */
    public static function postCurl(
        string $url,
        array $data,
        bool $isJson = true,
        int $timeout = 5,
        array $headers = []
    ) {
        $client = new HttpClient($url);
        $client->setTimeout($timeout);
        $client->setHeaders($headers, false, false);
        if ($isJson) {
            $data     = json_encode($data, JSON_UNESCAPED_UNICODE);
            $response = $client->postJson($data);
        } else {
            $response = $client->post($data);
        }
        self::checkCurlResponse($response);
        return $response->getBody();
    }


    /**
     * get
     * @param string $url 地址
     * @param int $timeout 超时时间，秒
     * @param array $headers header头
     * @return mixed
     * @throws BizException
     * @throws InvalidUrl
     */
    public static function getCurl(string $url, int $timeout = 5, array $headers = [])
    {
        $client = new HttpClient($url);
        $client->setTimeout($timeout);
        $client->setHeaders($headers, false, false);
        $response = $client->get();
        self::checkCurlResponse($response);
        return $response->getBody();
    }


    /**
     * delete
     * @param string $url 地址
     * @param int $timeout 超时时间，秒
     * @param array $headers header头
     * @return mixed
     * @throws BizException
     * @throws InvalidUrl
     */
    public static function deleteCurl(string $url, int $timeout = 5, array $headers = [])
    {
        $client = new HttpClient($url);
        $client->setTimeout($timeout);
        $client->setHeaders($headers, false, false);
        $response = $client->delete();
        self::checkCurlResponse($response);
        return $response->getBody();
    }


    /**
     * put
     * @param string $url 地址
     * @param  $data 数据
     * @param bool $isJson 是否json格式
     * @param int $timeout 超时时间，秒
     * @param array $headers header头
     * @return mixed
     * @throws BizException
     * @throws InvalidUrl
     */
    public static function putCurl(string $url, $data, bool $isJson = true, int $timeout = 5, array $headers = [])
    {
        $client = new HttpClient($url);
        $client->setTimeout($timeout);
        $client->setHeaders($headers);
        if ($isJson) {
            $data = json_encode($data, JSON_UNESCAPED_UNICODE);
        }
        $response = $client->put($data);
        self::checkCurlResponse($response);
        return $response->getBody();
    }


    /**
     * post xml
     * @param string $url 地址
     * @param string $data 数据
     * @param int $timeout 超时时间，秒
     * @param array $headers header头
     * @param array $options options
     * @return mixed
     * @throws BizException
     * @throws InvalidUrl
     */
    public static function postXmlCurl(
        string $url,
        string $data,
        int $timeout = 5,
        array $headers = [],
        array $options = []
    ) {
        $client = new HttpClient($url);
        $client->setTimeout($timeout);
        $client->setHeaders($headers, false, false);
        $response = $client->postXml($data);
        if (!empty($options)) {
            foreach ($options as $key => $value) {
                $client->setClientSetting($key, $value);
            }
        }
        self::checkCurlResponse($response);
        return $response->getBody();
    }


    /**
     * 验证网络状态码
     * @param Response $response 请求
     * @throws BizException
     */
    private static function checkCurlResponse(Response $response)
    {
        $errCode    = $response->getErrCode();
        $statusCode = $response->getStatusCode();

        if ($statusCode < 0 || $errCode != 0) {
            $msg = (new NetworkEnum())->getMessage(NetworkEnum::NETWORK_ERROR);
            throw new BizException(NetworkEnum::class, NetworkEnum::NETWORK_ERROR, $msg . "({$errCode}{$statusCode})");
        }
    }
}
